跳到主要内容

PowerShell

本文大量参考: 官方教程 zhuanlan powershell

问题

控制台换行

控制台换行 ` 注意是英文的

正文

快捷键

先来了解一下功能键和快捷键 ALT+F7 清除命令的历史记录 PgUp PgDn 显示当前会话的第一个命令和最后一个命令 Enter 执行当前命令 End 将光标移至当前命令的末尾 Del 从右开始删除输入的命令字符 Esc 清空当前命令行 F2 自动补充历史命令至指定字符 (例如历史记录中存在Get-Process,按F2,提示"Enter char to copy up to",键入 S,自动补齐命令:Get-Proce) F4 删除命令行至光标右边指定字符处 F7 对话框显示命令行历史记录 F8 检索包含指定字符的命令行历史记录 F9 根据命令行的历史记录编号选择命令,历史记录编号可以通过F7查看 ←/→ 左右移动光标↑/↓ 切换命令行的历史记录 Home 光标移至命令行最左端 Backspace 从右删除命令行字符 Ctrl+C 取消正在执行的命令 Ctrl+←/→ 在单词之间移动光标 Ctrl+Home 删除光标最左端的所有字符 Tab 自动补齐命令或者文件名

前置知识

换行符

`n

什么是Cmdlets

  • 可执行命令/PowerShell中的函数

  • [<动词>-<名词>][-<参数> <值>] 例如:-Get-Content -Path 'C:\' 详细动词列表

    常用的

    意思动词意思动词意思动词
    搜索Search得到Get打开Open
    选择Select隐藏Hide优化Optimize
    设置Set加入Join弹出Pop
    显示ShowLock推动Push
    跳过Skip移动Move重做Redo
    分裂Split新的New删除Remove
    解锁Unlock开关Switch重命名Rename
    监视Watch撤消Undo重置Reset

什么是PoweShell Pipeline

20200419001502 就是管道|

在自己的脚本里实现 20200419002805

Begin, Process, End 是管道语句块

get-process | select -last 5 | & {
begin {
"开始准备环境"
}
process
{
$_.Name
}
end {
"开始清理环境"
}
}
#输出结果为:
开始准备环境
wlcommsvc
WLIDSVC
WLIDSVCM
WmiPrvSE
XDict
开始清理环境

在脚本上使用管道

低速顺序模式

如果你在脚本中使用管道,脚本收集上一个语句的执行结果,默认保存在$input自动变量中。但是直到上一条语句完全执行完,管道脚本才会执行。所以实际就是传递一个对象的数组进来,获取之后通过foreach遍历数组

pipeline.ps1

# 效果,如果后缀是exe则输出红色的字体,否则是绿色 
foreach ($element in $input)
{
if($element.Extension -eq ".exe")
{
Write-Host -fore "red" $element.Name
}
else
{
Write-Host -fore "Green" $element.Name
}
}

执行脚本:

PS E:> ls $env:windir | .pipeline.ps1

注:$env:windir :从环境变量中获取系统目录 (绝对路径) 这个 $env 就是环境变量的意思,例如 $env:Path 就是返回这个Path的值

如果这样执行:

PS E:> ls $env:windir  -Recurse | .pipeline.ps1

控制台会被冻结,因为存储的中间结果在玩命的吃内存(没有释放内存)。这个也是低速顺序模式的缺点。

高速流模式

在Powershell脚本的处理中,绝大多数情况下遇到的都是集合,一旦上一条命令产生一个中间结果,下一条命令就对这个中间结果及时处理,及时释放资源。这样可以节省内存,也减少了用户的等待时间。在处理大量数据时,尤其值得推荐。高速流模式的管道定义包括三部分:begin,process,end。上面的描述中提到了中间结果,中间结果保存在$_自动化变量中。

begin
{
Write-Host "管道脚本环境初始化"
}
process
{
$ele=$_
if($_.Extension -ne "")
{
switch($_.Extension.tolower())
{
".ps1" {"脚本文件:"+ $ele.name}
".txt" {"文本文件:"+ $ele.Name}
".gz" {"压缩文件:"+ $ele.Name}
}
}
}
end
{
Write-Host "管道脚本环境恢复"
}

执行脚本文件:

PS E:> ls | .pipeline.ps1
管道脚本环境初始化
文本文件:a.txt
压缩文件:Metrol.tar.gz
脚本文件:MyScript.ps1
脚本文件:pipeline.ps1
脚本文件:PSLib.ps1
管道脚本环境恢复

执行策略限制

PowerShell 一般初始化情况下都会禁止脚本执行。脚本能否执行取决于PowerShell的执行策略。 只有管理员才有权限更改这个策略。非管理员会报错。 查看脚本执行策略,可以通过在 PowerShell 控制台直接输入: Get-ExecutionPolicy 更改脚本执行策略,可以管理员启动PowerShell,在控制台输入: Set-ExecutionPolicy <策略>

20200419114441

如果要使用脚本功能又要兼顾安全性,我们就选择RemoteSigned 即在以管理员身份允许的 PowerShell 输入 Set-ExecutionPolicy RemoteSigned

常用工具

也可以用PowerShell打开一些系统工具 notepad:记事本 calc:计算器 mspaint:画图

帮助系统

查找命令(通配符的使用): gal te :就可以找到后面是te的命令 同理:gal a :就可以找到a开头的命令 gal gservice gal 是get-alias的简称

get-help 命令 -online 可以自动打开一个外部文档 get-help 命令 -ShowWindow 可以自动打开一个本地文档 例如: Get-Help Write-Output -ShowWindow get-help *关键字* 也可以用来查找命令

cmdlet get-alias:获取别名,就是把cmd之前的类似cdcls 这类命令与 cmdlet 命令对应

常用命令

常用的cmdlet

输入&输出

输入输出函数

PowerShell提供了 Read-Host 命令,可以接收返回用户在控制台输入的字符

$name=read-host "请输入你的名字" 
#会把提示信息打印到PS控制台,也可以不写提示信息
<#执行+输入 结果:
请输入你的名字: Nougat
#>
$name
=>Nougat

有两种输出命令 Write-HostWrite-Output 若输出字符串不包含空白字符可以不加引号Write-Host当需要展示一个特定信息,比如使用其他颜色来吸引人们的注意力的时候,可使用 Write-Host 命令 Write-Host 和其他Cmdlets一样使用管道,但是它不放置任何数据道管道中。反而会直接写到宿主应用程序的界面。正如此,可以使用-ForegroundColor 和 -BackgroundColor 参数将前景和背景设置为其他颜色:

write-host "啊哈" -ForegroundColor White -BackgroundColor Red
=>啊哈

注:不是每个使用PowerShell的应用程序都支持其他颜色,也并不是每个应用程序都支持所有颜色。 该输出方法不适用于常规的输出结果,因为 Write-Host 命令输出到屏幕的任何东西都无法被捕捉。若执行远程命令或无人值守命令(纯自动化), Write-Host 可能不会按照你的预期工作。因此,此命令仅仅用于与人进行直接交互。

输出到文件里

$str|Out-File -FilePath .\yxh.txt -Encoding utf8
ForEach-Object

迭代对象 对输入对象集合中的每个项目执行操作 $_表示当前处理对象 常用参数:-Begin ,-Process, -End

# 例1:循环打印字符
'You','Me'| ForEach-Object{"Say $_"}
=>Say You
Say Me

# 例2:把日志信息输出到Events.txt
# 这里用了-Begin ,-Process, -End参数,-Begin和-End分别输出开头时间,完成时间(-Begin和-End只执行一次)
$Events = Get-EventLog -LogName System -Newest 1000
$events | ForEach-Object -Begin {Get-Date} -Process {Out-File -FilePath Events.txt -Append -InputObject $_.Message} -End {Get-Date}
Where-Object

筛选对象

'You','Me'| Where-Object{$_ -match 'u'}
=> You
Select-Object

选择对象/属性 常用参数: -First 选择的数量(从开头开始数) -Last 选择的数量(从结尾开始数) -Skip 跳过的数量 -SkipLast 从结尾开始跳过的数量 -Property 作用是输出对象的属性值,输出的为属性名加属性值(输入对象的属性名字,可以是数组用,分隔) -Unique 当多个对象的属性值相同时只处理一个 -ExpandProperty 只输出属性值

# -Property  输出的为属性名加属性值
Get-ComputerInfo | Select-Object -Property OsName
=>OsName
------
Microsoft Windows 10 专业版

# -ExpandProperty 只输出属性值
Get-ComputerInfo | Select-Object -ExpandProperty OsName
=> Microsoft Windows 10 专业版

# -First 2 选择前2个对象
Get-ChildItem | Select-Object -First 2
=>
目录: C:\Users\alsritter\Desktop\tmp


Mode LastWriteTime Length Name
---- ------------- ------ ----
da---- 2020/4/18 15:03 MarkDown文本
-a---- 2020/4/19 0:50 176272 Events.txt
-Replace

搜索或替换字符串中的文本 支持正则表达式

'i like tea' -Replace 'tea','coffee'
=> i like coffee

'i like tea' -Replace '\s','_'
=> i_like_tea
-Join

连接字符串 支持插入分隔符

-join('a','b','c')
=>abc

# 用.做连接
'127','a','b','c' -join '.'
=> 127.0.0.1
Out-File

输出到指定目录 例:把所有的md文件传到一个文件上的命令

Get-ChildItem *.md -Recurse|Get-Content -Encoding UTF8 |Out-File ./tep.txt -Encoding UTF8
-whatif

可以告诉用户这个命令执行后会发生什么

get-module

查看当前加载的模块 -ListAvailable :查看可用模块

get-process

查看进程

Get-Member

获取对象的属性和方法,对象 使用例:Get-Service | Get-Member Get-Member简称gm

语法

PowerShell变量名也对大小写不敏感

  • 行注释: #
  • 块注释: <##>

代码块

PowerShell 是一种块结构的语言,这些块用 { 和 } 来界定,代码块可以包含任意多条语句

{
<#代码行1#>
<#代码行2#>
{
<#代码行3#>
<#代码行4#>
}
# 每条语句如果在一行则以`;`分隔开
<#代码行5#>;<#代码行6#>;
}
PS E:> @'
>> Get-Date
>> $Env:CommonProgramFiles
>> #Script End
>> "files count"
>> (ls).Count
>> #Script Really End
>>
>> '@ > myscript.ps1
param(
# 这里定义变量
)
Begin{
# 开始前操作,可以省略(只执行一次)
}
Process{
# 这里执行主要的操作
}
End{
# 结束操作,可以省略(只执行一次)
}
# 创建一个Learn1.ps1,里面输入
Process{
# 这里执行主要的操作
$_
}

# 控制台输入
PS C:\Users\alsritter\Desktop\tmp> "hello","Shell"| .\Learn1.ps1
# 输出为
hello
Shell

数据类型

变量

运行时数据的存储 计算结果,字符串等

PowerShell是动态类型

$<变量名> = <值>
#例如 $surname = "john"
# $length = 32
预定义变量

null空值null 空值true 真 falsefalse 假_ 当前处理的元素 Home用户的主目录Home 用户的主目录? 前一命令执行状态,成功(Ture) 或者 失败(False)

删除变量

如果不想继续使用自定义的变量,可以使用del variable:变量名的方法删除变量,注意此处无$符号

$a=0
$a -eq $null
False
del variable:a
$a -eq $null
True
静态类型

一般对 PowerShell 变量重新赋值时,变量类型会自动改变,这是动态语言的特点; 而 PowerShell 的亲兄弟C#是静态强类型的,所以 PowerShell 也可以使用静态强类型,静态类型语言带来的严谨性能避免不必要的错误。 可以在变量前添加类型限定符使该变量变为静态类型,可以确保变量的类型不会随着赋值而改变

[int]$num=123 #正确
[int]$num=ls <#错误
无法将“System.Object[]”类型的“System.Object[]”值转换为“System.Int32”类型。
所在位置 行:1 字符: 1
+ [int]$num=ls
+ ~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
#>

数组

创建 --> @(<元素>,<元素>,<元素>,...)
索引 --> <数组>[<索引>]

# 例如:
$temp = @(<1>,<"元素">,<"元素">)
$temp[0]
#因为是动态类型,所以数组里面可以是任意类型

哈希表

创建 --> @{<键>=<值>;...} 索引 --> <哈希表>[<键>]

枚举

例:

enum VersionType{
SoftwareVersion = 1
HardwareVersion = 2
}

# 使用
[VersionType]::SoftwareVersion

运算符

逻辑运算符

! 不等于 -not-and-or

比较运算符

Powershell 中的比较运算符 -eq :等于 -ne :不等于 -gt :大于 -ge :大于等于 -lt :小于 -le :小于等于 -contains :包含 -notcontains :不包含

调用运算符

& 可用于调用脚本块或者命令/函数的名称 用法如下:

$a = { Get-Process | Select -First 2}  #获取处理器信息排名前二的两条记录
&$a

. 可用于方法调用 用法如下:

$a = "这是字符串"
$a.substring(0,3)

:: 用于静态方法调用
用法如下:

[DateTime]::IsLeapYear(2008)
结果:True
[DateTime]::Now #返回当前时间

字符串运算符

+ 连接两个字符串 * 按指定次数重复字符串 -f 设置字符串格式 -replace 替换运算符 用法:"abcd" -replace "bc","TEST" 返回结果:aTESTd -match 正则表达式匹配 -like 通配符匹配

流程控制

  • if-else分支
If(<条件>){
<语句>
}
ElseIf(<条件>){
<语句>
}
Else{
<语句>
}
  • switch分支
Switch(<条件>){
<测试值>{<语句>;break}
...
Default{<语句>}
}

循环

也支持breakcontinue

For循环

For(<开始值>;<循环条件>;<迭代步骤>){
<语句>
}
# 例子
$sum=0
for($i=1;$i -le 100;$i++)
{
$sum+=$i
}
$sum


ForEach(<元素> in <集合> ){
<语句>
}

# 例:
# 打印出windows目录下大于1mb的文件名
foreach($file in dir c:\windows)
{
if($file.Length -gt 1mb)
{
$File.Name
}
}

While循环

While(<循环条件>){
<语句>
}

Do{
<语句>
}While(<循环条件>)

函数

函数是自定义的 Powershell 代码,有三个原则: 简短:函数名简短,并且显而易见。 聚合:函数可以完成多个操作。

  • 封装和扩展:将一批 Powershell 语句进行封装,实现全新的功能需求。 函数的结构由三部分组成:函数名,参数,函数体
function FuncName(args[]) #括号可省略
{
<#代码段#>
}

$args 万能参数

给一个函数定义参数最简单的是使用$args这个内置的参数。它可以识别任意个参数。尤其适用那些参数可有可无的函数。

function sayHello
{
if($args.Count -eq 0)
{
"No argument!"
}
else
{
$args | foreach {"Hello,$($_)"}
}
}
#无参调用
sayhello
#输出
No argument!

#一参调用
sayhello "World!" #也可以写成sayhello("World!")
#输出
Hello,World!


#多参数调用
$str="it's me."
sayhello 123 "aha" $str #如果字符串不包含空白字符(比如空格),引号可以不写,参数之间用空格隔开
<#输出
Hello,123
Hello,aha
Hello,it's me.
#>

$arg 是一个数组,可以用它很方便的写出求和函数

function Add
{
$sum=0
$args | foreach {$sum=$sum+$_}
$sum
}
Add 10 7 3 100
#120

使用固定参数

function StringContact($str1,$str2)
{
return $str1+$str2
}

<!-- @import "[TOC]" {cmd="toc" depthFrom=1 depthTo=6 orderedList=false} -->

StringContact LN P
#StringContact -str1 word -str2 press
#StringContact("word","press")
LNP
wordpress
  • 给参数定义默认值
function stringContact($str1="LN",$str2="P")
{
return $str1+$str2
}

stringContact
LNP

面向对象

完全访问.Net框架

创建对象

-New-Object <类型名><构造函数-参数>

# 例
$version = New-Object System.Version
# 创建时添加构造函数
$version = New-Object System.Version 3,6

访问态的静态元素

  • 访问类通过[<类型名>]
  • 类型转换 例如:[System.Version] "1.0.3.4"

-类方法,枚举,... -例如:

[System.Version]::New()
[System.ConsoleColor]::Red

创建类


# 语法
class <类名>{
<hidden|static>
[<类型名>]$<属性名>

<hidden|static>
<构造函数名>(<参数>,..){
...
}

<hidden|static>
[<返回类型>]<方法名>(<参数>,..){
...
}
}

# 例如
class MyVersion{
[Int]$Major
[Int]$Minor
[Int]$Build
[Int]$Rev

MyVersion(){
$this.Major,$this.Minor,$this.Build,$this.Rev = 0
}

MyVersion($Major,$Minor,$Build,$Rev){
$this.Major = $Major
$this.Minor = $Minor
$this.Build = $Build
$this.Rev = $Rev
}

[String]ToString(){
return ($this.Major,$this.Minor,$this.Build,$this.Rev) -join "."
}

[System.Version]Convert(){
return [System.Version]$this.ToString()
}
}

# 使用
$MyVersionA = New-Object MyVersion
$MyVersionB = New-Object MyVersion 1,2,3,4

$MyVersionA.Minor
$MyVersionB.ToString()

自定义形参输入

[CmdletBinding()] :它的主要功能是让PowerShell脚本或者函数能够有cmdlet样式的参数绑定功能。 一般放在PowerShell的脚本或者函数中的第一行

使用例

[CmdletBinding()]

# 这个正则表达式检查输入是否是由三个.分隔的数字组成
Param Block(
[validatePattern('^(\d+\.)(3}\d+$)')]
[Parameter(Mandatory = $true)]
[String]
$VersionString
)

参数配置 [Parameter()] 属性 [<Type>] 期望的类型 $<Name> 参数名

// 例
[Parameter(Position = 0, Mandatory = true)]
public string UserName
{
get { return userName; }
set { userName = value; }
}
private string userName;
# Mandatory 设定方法的参数是否是必须的
# $false 可选的
# $true 必须的
[Parameter(Mandatory = <$false|$true>)]

# 参数验证
[validateSet(<元素>,<元素>,...)]
[validateLength(<最小值>,<最大值>)]
[validateRange(<最小值>,<最大值>)]
[validateScript({<表达式>})]
[validatePattern({<正则表达式>})]


模块

PowerShell中包括两种模块——脚本模块和二进制模块 脚本模块:它完全由PowerShell语法和环境编写,不需要切换到其他编译语言或者开发环境。

通过get-module 可以查看模块里面的Function 本质这个模块就是一个之前写好的Function,调用时就像调用普通的Cmdlet那样

创建一个模块

拓展名为psm1

待更新...

导入模块

待更新...